/**
 * Project 68th
 */

#include "../include/log4cppuse.h"
#include "../include/SocketIO.h"
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <strings.h>
#include <memory.h> 
#include <arpa/inet.h>
/**
 * SocketIO implementation
 */


/**
 * @param fd
 */
SocketIO::SocketIO(int fd) 
: _fd(fd)
{

}

SocketIO::~SocketIO() {
    /* close(_fd); */
}



Message SocketIO::readMessage()
{
    Message message;
    bzero(&message,sizeof(message));

#if 0
    char buf[65535] = {0};
    if(recv(_fd,&message.atg,sizeof(message.atg),0) <= 0)
    {
        LOG_ERROR("readMessage error -1");
        return Message();
    }
    if(recv(_fd,&message.length,sizeof(message.length),0) <= 0)
    {
        LOG_ERROR("readMessage error -1");
        return Message();
    }

    if(recv(_fd,&buf,message.length,0) <= 0)
    {
        LOG_ERROR("readMessage error -1");
        return Message();
    }
    message.msg = buf;
#endif
    char header[8];
    if(recv(_fd, header, sizeof(header), MSG_WAITALL) <= 0) {
        LOG_ERROR("readMessage header error");
        return Message();
    }
    memcpy(&message.atg, header, sizeof(message.atg));
    memcpy(&message.length, header + sizeof(message.atg), sizeof(message.length));

    // 网络字节序转主机字节序
    message.atg = ntohl(message.atg);
    message.length = ntohl(message.length);

    // 检查长度有效性
    if(message.length <= 0 || message.length > 65535) {
        string log="Invalid message length: " + to_string(message.length);
        LOG_ERROR(log.c_str());
        return Message();
    }
    
    if(message.length > 0) {
        vector<char> buffer(message.length);
        int bytesRead = recv(_fd, buffer.data(), message.length, MSG_WAITALL);
        if(bytesRead != message.length) {
            string log="Failed to read message body, expected " + to_string(message.length) + " bytes, but read " + to_string(bytesRead) + " bytes";
            LOG_ERROR(log.c_str());
            return Message();
        }
        message.msg.assign(buffer.data(), message.length);
    }


    string log="readMessage: 标志 tag="+to_string(message.atg)+" 消息长度 length="+to_string(message.length)+" 消息内容 message="+message.msg;
    cout << log << endl;
    LOG_DEBUG(log.c_str());
    return message;
}

void  SocketIO::writenMessage(const Message & message)
{
#if 1
    uint32_t net_tag = htonl(message.atg);
    uint32_t net_length = htonl(message.length);
     if (send(_fd, &net_tag, 4, 0) != 4) {
         LOG_ERROR("writenMessage  tag error -1");
         return ;
    }
    if (send(_fd, &net_length, 4, 0) != 4) {
        LOG_ERROR("writenMessage  length error -1");
        return ;
    }

    // 发送消息体
    if (message.length > 0) {
        if (send(_fd, message.msg.c_str(), message.length, 0) != message.length) {
            LOG_ERROR("writenMessage  msg error -1");
            return ;
        }
    }
#endif
#if 0
    if(send(_fd,&message.atg,sizeof(message.atg),0) <= 0)
    {
        LOG_ERROR("writenMessage  tag error -1");
        return;
    }
    if(send(_fd,&message.length,sizeof(message.length),0) <= 0)
    {
        LOG_ERROR("writenMessage length error -1");
        return;
    }
    if(send(_fd,&message.msg[0],message.length,0) <= 0)
    {
        LOG_ERROR("writenMessage msg error -1");
        return;
    }
#endif
}


//假设len = 10000，但是单次read的能力上限是1000
//那么为了实现读取10000个字符，可能需要进行多次read
int SocketIO::readn(char *buf, int len)
{
    //len是读取任务的字符总量，left代表剩余量
    int left = len;
    char *pstr = buf;
    int ret = 0;

    //因为read函数单次读取的数据量存在上限
    while(left > 0)
    {
        ret = ::read(_fd, pstr, left);
        //对当前进程（线程）而言发生了中断
        //中断触发，导致CPU的使用权被抢夺，后续应该继续执行
        if(-1 == ret && errno == EINTR)
        {
            continue;
        }
        else if(-1 == ret)
        {
            LOG_ERROR("read error -1");
            return -1;
        }
        else if(0 == ret)
        {
            break;
        }
        else
        {
            pstr += ret;
            left -= ret;
        }
    }

    return len - left;
}




int SocketIO::readLine(char *buf, int len)
{
    int left = len - 1;
    char *pstr = buf;
    int ret = 0, total = 0;

    while(left > 0)
    {
        //MSG_PEEK不会将缓冲区中的数据进行清空,只会进行拷贝操作
        ret = recv(_fd, pstr, left, MSG_PEEK);
        if(-1 == ret && errno == EINTR)
        {
            continue;
        }
        else if(-1 == ret)
        {
            LOG_ERROR("readLine error -1");
            return -1;
        }
        else if(0 == ret)
        {
            break;
        }
        else
        {
            for(int idx = 0; idx < ret; ++idx)
            {
                if(pstr[idx] == '\n')
                {
                    int sz = idx + 1;
                    readn(pstr, sz);
                    pstr += sz;
                    *pstr = '\0';//C风格字符串以'\0'结尾

                    return total + sz;
                }
            }

            readn(pstr, ret);
            total += ret;
            pstr += ret;
            left -= ret;
        }
    }
    *pstr = '\0';

    return total;

}

int SocketIO::writen(const char *buf, int len)
{
    int left = len;
    const char *pstr = buf;
    int ret = 0;

    //同样，一次write能写的数据量也有上限
    while(left > 0)
    {
        ret = write(_fd, pstr, left);
        if(-1 == ret && errno == EINTR)
        {
            continue;
        }
        else if(-1 == ret)
        {
            LOG_ERROR("writen error -1");
            return -1;
        }
        else if(0 == ret)
        {
            break;
        }
        else
        {
            pstr += ret;
            left -= ret;
        }
    }
    return len - left;
}

